package com.seventh.blekit;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.inuker.bluetooth.library.BluetoothClient;
import com.inuker.bluetooth.library.Code;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.connect.response.BleNotifyResponse;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.search.SearchRequest;
import com.inuker.bluetooth.library.search.SearchResult;
import com.inuker.bluetooth.library.search.response.SearchResponse;
import com.seventh.blekit.fix0629.SensorDef;
import com.vrseen.controller.DecodeNative;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import static com.inuker.bluetooth.library.Code.REQUEST_SUCCESS;

/**
 * Unity调用Android
 * <p>
 * Unity调用Android的方法
 */
public class FromUnity extends BaseUnity {
    private final UUID serviceUUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
    private final UUID characterUUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");

    //private final UUID serviceUUID = UUID.fromString("0000fddd-0000-1000-8000-00805f9b34fb");
    //private final UUID characterUUID = UUID.fromString("0000fdd1-0000-1000-8000-00805f9b34fb");
    private IBackListener backListener;
    private static FromUnity sFromUnity;
    private final BluetoothClient mClient;
    private final SearchRequest mRequest = new SearchRequest.Builder()
            .searchBluetoothClassicDevice(10000, 1) // 再扫经典蓝牙5s
            .searchBluetoothLeDevice(10000, 1)   // 先扫BLE设备3次，每次3s
            .build();
    private final BleConnectOptions mOptions = new BleConnectOptions.Builder()
            .setConnectRetry(3)   // 连接如果失败重试3次
            .setConnectTimeout(30000)   // 连接超时30s
            .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
            .setServiceDiscoverTimeout(20000)  // 发现服务超时20s
            .build();
    private SearchResult mCurrentResult;


    public synchronized static FromUnity getInstance(@NonNull Context context) {
        if (sFromUnity == null) {
            sFromUnity = new FromUnity(context);
        }
        return sFromUnity;
    }

    /**
     * @return Unity里面调用
     */
    public synchronized static FromUnity getInstance() {
        if (sFromUnity == null) {
            sFromUnity = new FromUnity(getUnityActivity());
        }
        return sFromUnity;
    }

    private FromUnity(@NonNull Context context) {
        super(context);
        this.mClient = new BluetoothClient(context);
    }

    /**
     * 搜索蓝牙设备
     */
    public void scan() {
        //由于BluetoothUtils.isBleSupported() 的Context未初始化导致判断异常
        //所以在局部初始化
        final SearchRequest mRequest = new SearchRequest.Builder()
                .searchBluetoothClassicDevice(5000, 1) // 再扫经典蓝牙5s
                .searchBluetoothLeDevice(5000, 1)   // 先扫BLE设备3次，每次3s
                .build();
        if (!mClient.isBleSupported()) {
            Toast.makeText(context, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!mClient.isBluetoothOpened()) {
            Toast.makeText(context, "请先打开蓝牙~", Toast.LENGTH_SHORT).show();
            return;
        }
        mClient.search(mRequest, new SearchResponse() {
            /**
             * 所有的目标设备
             */
            private List<SearchResult> filterResult = new ArrayList<>();

            @Override
            public void onSearchStarted() {
                Toast.makeText(context, "正在扫描蓝牙设备", Toast.LENGTH_SHORT).show();
                Log.e("print", "onSearchStarted");
            }

            @Override
            public void onDeviceFounded(SearchResult device) {
                String name = device.getName();
                //if (name.length() < 6 || !name.substring(0, 6).equalsIgnoreCase("Nordic")) {
                //    return;
                //}
                //if (!name.startsWith("VRSEEN")) {
                //    return;
                //}
                if (filterResult.contains(device)) {
                    return;
                }
                filterResult.add(device);
                if (!device.getName().equals("NULL")) {
                    Log.e("print", device.getName());
                    Log.e("print", device.getAddress());
                }
            }

            @Override
            public void onSearchStopped() {
                Log.e("print", "onSearchStopped");
                if (filterResult.isEmpty()) {
                    Toast.makeText(context, "未扫描到目标设备", Toast.LENGTH_LONG).show();
                } else {
                    showDialog(filterResult);
                }
            }

            @Override
            public void onSearchCanceled() {
                Log.e("print", "onSearchCanceled");
                Toast.makeText(context, "取消扫描蓝牙设备", Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 显示扫描结果
     */
    private void showDialog(final List<SearchResult> results) {
        CharSequence[] bleNames = new CharSequence[results.size()];
        for (int index = 0; index < bleNames.length; index++) {
            bleNames[index] = results.get(index).getName();
        }
        new AlertDialog.Builder(context)
                .setTitle("请选择连接的蓝牙设备")
                .setSingleChoiceItems(bleNames, -1, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        SearchResult result = results.get(which);
                        Log.e("print", "result:" + result.getName());
                        connect(result);
                    }
                }).setNegativeButton("取消", null)
                .setCancelable(false)
                .show();
    }

    private void connect(final SearchResult result) {
        mCurrentResult = result;
        mClient.connect(result.getAddress(), mOptions, new BleConnectResponse() {
            @Override
            public void onResponse(int code, BleGattProfile data) {
                Toast.makeText(context, Code.toString(code), Toast.LENGTH_SHORT).show();
                if (code == REQUEST_SUCCESS) {
                    notifyBle(result);
                }
            }
        });
    }


    //public void connect() {
    //    mClient.connect("EB:1E:26:D1:A5:72", mOptions, new BleConnectResponse() {
    //        @Override
    //        public void onResponse(int code, BleGattProfile data) {
    //            Toast.makeText(context, Code.toString(code), Toast.LENGTH_SHORT).show();
    //            if (code == REQUEST_SUCCESS) {
    //                notifyBle("EB:1E:26:D1:A5:72");
    //            }
    //        }
    //    });
    //}

    //private void notifyBle(String result) {
    //    mClient.notify(result, serviceUUID, characterUUID, new BleNotifyResponse() {
    //        @Override
    //        public void onNotify(UUID service, UUID character, byte[] value) {
    //            //String data = parseSensorData(value);
    //            //callUnity(getGameObjectName(), getFunctionName(), data);
    //            StringBuilder builder = new StringBuilder();
    //            builder.append(func(value[2], value[3]));
    //            builder.append(",");
    //            builder.append(func(value[4], value[5]));
    //            builder.append(",");
    //            builder.append(func(value[6], value[7]));
    //            builder.append(",");
    //            builder.append(func(value[8], value[9]));
    //            String data = builder.toString();
    //            // Log.e("print", System.currentTimeMillis() + " 接收到的数据 16:" + bytesToHex(value));
    //            callUnity("receiveObject", "onReceive", data);
    //            if (backListener != null) {
    //                backListener.onBack(SensorData.create(value));
    //            }
    //        }
    //
    //        @Override
    //        public void onResponse(int code) {
    //            if (code == REQUEST_SUCCESS) {
    //                Toast.makeText(context, "notify成功~", Toast.LENGTH_SHORT)
    //                        .show();
    //            } else {
    //                Toast.makeText(context, "notify失败~", Toast.LENGTH_SHORT)
    //                        .show();
    //            }
    //        }
    //    });
    //}

    /**
     * 解析传感器的数据
     */
    public static String parseSensorData(byte[] value) {
        DecodeNative.decode(value);
        float[] f4 = new float[]{-1, -1, -1, -1};
        DecodeNative.getPredict(f4);
        Log.e("print", " 接收到的数据 F4:" + Arrays.toString(f4));

        float[] f9 = new float[]{-1, -1, -1, -1, -1, -1, -1, -1, -1};
        DecodeNative.getLastData(f9);
//        float[] changeF4 = new float[]{-f4[1], -f4[2], f4[3], f4[0]};
        StringBuilder builder = new StringBuilder();
        builder.append(-f4[1]);
        builder.append(",");
        builder.append(-f4[2]);
        builder.append(",");
        builder.append(f4[3]);
        builder.append(",");
        builder.append(f4[0]);
        //角速度
        builder.append(",");
        builder.append(f9[0]);
        builder.append(",");
        builder.append(f9[1]);
        builder.append(",");
        builder.append(f9[2]);
        builder.append(",");
        //加速度
        builder.append(f9[3]);
        builder.append(",");
        builder.append(f9[4]);
        builder.append(",");
        builder.append(f9[5]);
        Log.e("print", "data:" + builder.toString());
        return builder.toString();
    }

    public void setBackListener(IBackListener backListener) {
        this.backListener = backListener;
    }

    private void notifyBle(SearchResult result) {
        mClient.notify(result.getAddress(), serviceUUID, characterUUID, new BleNotifyResponse() {
            @Override
            public void onNotify(UUID service, UUID character, byte[] value) {
                //String data = parseSensorData(value);
                //callUnity(getGameObjectName(), getFunctionName(), data);
                //StringBuilder builder = new StringBuilder();
                //builder.append(func(value[2], value[3]));
                //builder.append(",");
                //builder.append(func(value[4], value[5]));
                //builder.append(",");
                //builder.append(func(value[6], value[7]));
                //builder.append(",");
                //builder.append(func(value[8], value[9]));
                //String data = builder.toString();
                //// Log.e("print", System.currentTimeMillis() + " 接收到的数据 16:" + bytesToHex(value));
                //callUnity("receiveObject", "onReceive", data);
                //if (backListener != null) {
                //    backListener.onBack(SensorData.create(value));
                //}
                Log.e("print", System.currentTimeMillis() + "==" + value.length + " 接收到的数据16:" + bytesToHex(value));
                SensorDef sensorDef = SensorDef.create(value);
                Log.e("print", sensorDef.toString());
                Log.e("printunity", sensorDef.createUnityMsg());
                callUnity(getGameObjectName(), getFunctionName(), sensorDef.createUnityMsg());
            }

            @Override
            public void onResponse(int code) {
                if (code == REQUEST_SUCCESS) {
                    Toast.makeText(context, "notify成功~", Toast.LENGTH_SHORT)
                            .show();
                } else {
                    Toast.makeText(context, "notify失败~", Toast.LENGTH_SHORT)
                            .show();
                }
            }
        });
    }

    /**
     * 字节数组转16进制
     *
     * @param bytes 需要转换的byte数组
     * @return 转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            sb.append("0x");
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
            sb.append(",");
        }
        return sb.toString();
    }

    public static String byteToString(byte value) {
        String hex = Integer.toHexString(value & 0xFF);
        if (hex.length() < 2) {
            hex = "0" + hex;
        }
        return hex;
    }

    public void disconnect() {
        if (mCurrentResult != null) {
            mClient.disconnect(mCurrentResult.getAddress());
        }
    }
    //Unity
//    float func(byte bt0, byte bt1) {
//        byte a = (byte) (bt0 & 0x80);
//        float x = 0f;
//        if (a != 0) {
//            byte bt00 = (byte) (bt0 & 0x7f);
//            x = -((float) (bt00 * 256 + bt1)) / 1000f;
//        } else {
//            x = ((float) (bt0 * 256 + bt1)) / 1000f;
//        }
//        return x;
//    }

    /**
     * 第一位带符号，第二位不带符号
     */
    private float func(byte bt0, byte bt1) {
        byte a = (byte) (bt0 & 0x80);
        int reset = Integer.parseInt(byteToString(bt1), 16);
        if (a != 0) {
            byte bt00 = (byte) (bt0 & 0x7f);
            return -((float) (bt00 * 256 + reset)) / 1000f;
        } else {
            return ((float) (bt0 * 256 + reset)) / 1000f;
        }
    }
}
